﻿// 2022/4/1: 首个版本
// 2023/2/15: 远程采集模式时禁用
// 2023/4/10: 增加Load/Save方法

using System;
using System.Linq;
using System.Xml;
using ASEva;
using ASEva.Utility;

namespace CommonSource
{
    class AudioConfig
    {
        public AudioConfig()
        {
            RecordDriverID = null;
            RecordDeviceID = null;
            ReplayDriverID = null;
            ReplayDeviceID = null;
        }

        public static AudioConfig Load(object caller)
        {
            var config = new AudioConfig();
            var configString = Agency.GetModuleConfig(caller, "audio.system");
            config.SetConfig(configString);
            return config;
        }

        public void Save(object caller)
        {
            Agency.SetModuleConfig(caller, "audio.system", GetConfig());
        }

        public void SetConfig(String config)
        {
            if (String.IsNullOrEmpty(config)) return;

            var xml = new XmlDocument();
            xml.LoadXml(config);

            var cp = new AttributeParser(xml.DocumentElement);

            var recordDriver = cp.ParseString("record_driver", null);
            var recordDevice = cp.ParseString("record_device", null);
            var replayDriver = cp.ParseString("replay_driver", null);
            var replayDevice = cp.ParseString("replay_device", null);

            RecordDriverID = null;
            RecordDeviceID = null;
            if (isRecordDeviceAvailable(recordDriver, recordDevice))
            {
                RecordDriverID = recordDriver;
                RecordDeviceID = recordDevice;
            }

            if (isReplayDeviceAvailable(replayDriver, replayDevice))
            {
                ReplayDriverID = replayDriver;
                ReplayDeviceID = replayDevice;
            }
        }

        public String GetConfig()
        {
            var xml = Xml.Create("root");

            var cw = new AttributeWriter(xml.DocumentElement);

            cw.WriteString("record_driver", RecordDriverID);
            cw.WriteString("record_device", RecordDeviceID);
            cw.WriteString("replay_driver", ReplayDriverID);
            cw.WriteString("replay_device", ReplayDeviceID);

            return xml.InnerXml;
        }

        public ConfigStatus GetConfigStatus()
        {
            var appMode = Agency.GetAppMode();
            if (appMode == ApplicationMode.Online)
            {
                if (RecordDeviceID == null) return ConfigStatus.Disabled;
                else if (!isRecordDeviceAvailable(RecordDriverID, RecordDeviceID)) return ConfigStatus.EnabledWithError;
                else return ConfigStatus.Enabled;
            }
            else if (appMode == ApplicationMode.Offline || appMode == ApplicationMode.Replay)
            {
                if (ReplayDeviceID == null) return ConfigStatus.Enabled;
                else if (!isReplayDeviceAvailable(ReplayDriverID, ReplayDeviceID)) return ConfigStatus.EnabledWithError;
                else return ConfigStatus.Enabled;
            }
            else return ConfigStatus.Disabled;
        }

        public void DisableAll()
        {
            RecordDriverID = null;
            RecordDeviceID = null;
        }

        public void DisableErrorPart()
        {
            var appMode = Agency.GetAppMode();
            if (appMode == ApplicationMode.Online)
            {
                if (RecordDeviceID != null && !isRecordDeviceAvailable(RecordDriverID, RecordDeviceID))
                {
                    RecordDriverID = null;
                    RecordDeviceID = null;
                }
            }
            else if (appMode == ApplicationMode.Offline || appMode == ApplicationMode.Replay)
            {
                if (ReplayDeviceID != null && !isReplayDeviceAvailable(ReplayDriverID, ReplayDeviceID))
                {
                    ReplayDriverID = null;
                    ReplayDeviceID = null;
                }
            }
        }

        public String RecordDriverID { get; set; }
        public String RecordDeviceID { get; set; }
        public String ReplayDriverID { get; set; }
        public String ReplayDeviceID { get; set; }

        private bool isRecordDeviceAvailable(String recordDriver, String recordDevice)
        {
            var drivers = Agency.GetAudioDrivers();
            if (drivers != null && recordDriver != null && recordDevice != null)
            {
                foreach (var d in drivers)
                {
                    if (d.DriverID != recordDriver) continue;
                    var devices = Agency.GetAudioRecordDevices(d.DriverID);
                    if (devices != null)
                    {
                        foreach (var device in devices)
                        {
                            if (device.DeviceID != recordDevice) continue;
                            return true;
                        }
                    }
                    break;
                }
            }
            return false;
        }

        private bool isReplayDeviceAvailable(String replayDriver, String replayDevice)
        {
            var drivers = Agency.GetAudioDrivers();
            if (drivers != null && replayDriver != null && replayDevice != null)
            {
                foreach (var d in drivers)
                {
                    if (d.DriverID != replayDriver) continue;
                    var devices = Agency.GetAudioReplayDevices(d.DriverID);
                    if (devices != null)
                    {
                        foreach (var device in devices)
                        {
                            if (device.DeviceID != replayDevice) continue;
                            return true;
                        }
                    }
                    break;
                }
            }
            return false;
        }
    }
}
